package goim_decode

import (
	"bufio"
	"encoding/binary"
)

type Proto struct {
	PackLen   int32  // package length
	HeaderLen int16  // header length
	Ver       int16  // protocol version
	Operation int32  // operation for request
	Seq       int32  // sequence number chosen by client
	Body      []byte // body
}

// Decoder goim 协议解码，参考 benchmarks/client/main.go:213 tcpReadProto。
// 知道协议中属性长度和编码顺序就可以解码。
func Decoder(reader *bufio.Reader, proto *Proto) (err error) {
	// decode package length
	if err = binary.Read(reader, binary.BigEndian, &proto.PackLen); err != nil {
		return
	}
	// decode header length
	if err = binary.Read(reader, binary.BigEndian, &proto.HeaderLen); err != nil {
		return
	}
	// decode version
	if err = binary.Read(reader, binary.BigEndian, &proto.Ver); err != nil {
		return
	}
	// decode operation
	if err = binary.Read(reader, binary.BigEndian, &proto.Operation); err != nil {
		return
	}
	// decode sequence id
	if err = binary.Read(reader, binary.BigEndian, &proto.Seq); err != nil {
		return
	}

	var (
		n, t    int
		bodyLen = int(proto.PackLen - int32(proto.HeaderLen))
	)
	if bodyLen > 0 {
		proto.Body = make([]byte, bodyLen)
		for {
			if t, err = reader.Read(proto.Body[n:]); err != nil {
				return
			}
			if n += t; n == bodyLen {
				break
			}
		}
	} else {
		proto.Body = nil
	}
	return nil
}
